package 操作.工具类

import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.toLowerCase
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.atStartOfDayIn
import kotlinx.datetime.atTime
import kotlinx.datetime.minus
import kotlinx.datetime.plus
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlin.math.absoluteValue

object 时间操作 {

    /**
     * @return Pair<开始时间戳，结束时间戳>
     */
    fun 取月份时间戳(year: Int, month: Int): Pair<Long, Long> {
        val timeZone = TimeZone.currentSystemDefault()

        // 当月第一天 00:00:00
        val startOfMonth = LocalDate(year, month, 1)
            .atStartOfDayIn(timeZone)
            .epochSeconds

        // 计算当月最后一天
        val lastDay = LocalDate(year, month, 1)
            .plus(1, DateTimeUnit.MONTH).minus(1, DateTimeUnit.DAY)

        // 当月最后一天 23:59:59
        val endOfMonth = lastDay.atTime(23, 59, 59)
            .toInstant(timeZone)
            .epochSeconds

        return Pair(startOfMonth, endOfMonth)
    }


    /**
     * @param 时间戳 时间戳
     * @param 格式 返回日期类型 yyyy-MM-dd HH:mm:ss  年费-月份-日  时:分:秒   注意月份为大写MM
     */
    fun 时间戳到文本(时间戳 : Long, 格式 : String = "yyyy-MM-dd HH:mm:ss") : String{
        var milSecond = 时间戳
        if (milSecond.toString().length <= 10) {
            milSecond *= 1000
        }

        val t =  Instant.fromEpochMilliseconds(milSecond).toLocalDateTime(TimeZone.UTC)
        return 格式.replace("yyyy",t.year.toString())
            .replace("MM",t.monthNumber.toString().let {
                if (it.length == 1) "0$it"
                else it
            })
            .replace("dd",t.dayOfMonth.toString().let {
                if (it.length == 1) "0$it"
                else it
            })
            .replace("HH",t.hour.toString().let {
                if (it.length == 1) "0$it"
                else it
            })
            .replace("mm",t.minute.toString().let {
                if (it.length == 1) "0$it"
                else it
            })
            .replace("ss",t.second.toString().let {
                if (it.length == 1) "0$it"
                else it
            })
    }



    // LocalTime().toSecondOfDay()
    fun 日秒到时分(秒: Int): String {
        if (秒 < 0) return "00:00"
        if (秒 > 86400) return "23:59"
        return 到时分(LocalTime.fromSecondOfDay(秒))
    }
    fun 到时分(time : LocalTime) : String{
        return let {
            time.hour.toString().padStart(2,'0') +
                    ":" + time.minute.toString().padStart(2,'0')
        }
    }
    fun 到年月(date : LocalDate) : String{
        return date.year.toString() + "/" +
                date.monthNumber.toString().padStart(2,'0')
    }

    // 返回周一周二、、类推
    fun 取星期文本(date: LocalDate) : String{
        val ls = when(Locale.current.language){
            "en" -> listOf("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday")
            // 默认中文
            else  -> listOf("星期一","星期二","星期三","星期四","星期五","星期六","星期日")
        }
        return ls[date.dayOfWeek.ordinal]
    }

    // 返回月份完成名称，入一月
    fun 取月日文本(date: LocalDate) : String{
        return when(Locale.current.language) {
            "en" -> {
                val month = date.month.name.take(3).toLowerCase(Locale.current).capitalize()  // 首字母大写
                "$month ${date.dayOfMonth}"
            }
            else -> {
                "${date.monthNumber}月${date.dayOfMonth.toString().padStart(2, '0')}日"
            }
        }
    }

    // 返回日时间并对应的文本，如 1 点，就返回 凌晨 1点
    fun 小时到文本(hour : Int) : String{
        return when(Locale.current.language){
            "en" -> {
                val name = when (hour) {
                    in 0..11 -> "AM"
                    else -> "PM"
                }
                name + " " + hour.toString().padStart(2,'0') + ":00"
            }

            else -> {
                val name = when(hour){
                    in 0..5 -> "凌晨"
                    in 6..11 -> "上午"
                    in 12..17 -> "下午"
                    else -> "晚上"
                }
                name + " " +  hour.toString().padStart(2,'0') + "点"

            }
        }
    }



    // 时间戳转 LocalDateTime
    fun toDateTime(时间戳 : Long) : LocalDateTime {
        var 毫秒 = 时间戳
        if (毫秒.toString().length < 13) {
            毫秒 *= 1000
        }

        return Instant.fromEpochMilliseconds(毫秒).toLocalDateTime(TimeZone.UTC)
    }

    fun 格式化日期时间(目标时间日期 : LocalDateTime): String{
        val 当前时间 = Instant.fromEpochSeconds(kotlinx.datetime.Clock.System.now().epochSeconds)
        val 当前时间日期 = 当前时间.toLocalDateTime(TimeZone.currentSystemDefault())

        // 如果是今天
        if (目标时间日期.date.year == 当前时间日期.date.year &&
            目标时间日期.date.monthNumber == 当前时间日期.date.monthNumber &&
            目标时间日期.date.dayOfMonth == 当前时间日期.date.dayOfMonth) {
            return "${目标时间日期.hour.toString().padStart(2, '0')}:${目标时间日期.minute.toString().padStart(2, '0')}"
        }

        // 一周内
        val 一周秒数 = 7 * 24 * 60 * 60
        if ((目标时间日期.toInstant(TimeZone.currentSystemDefault()).epochSeconds
                    - 当前时间.epochSeconds).absoluteValue < 一周秒数) {
            return 取星期文本(目标时间日期.date)
        }

        // 一年内
        if (目标时间日期.date.year == 当前时间日期.date.year) {
            return "${目标时间日期.monthNumber}月${目标时间日期.dayOfMonth}日"
        }

        // 超过一年
        return "${目标时间日期.year}/${目标时间日期.monthNumber}/${目标时间日期.dayOfMonth}"
    }

    /**
     * 上周  上个月  五分钟前等等。。 让时间看起来更自然
     */
    fun 格式化日期时间(时间戳: Long): String {
        if (时间戳 <= 0) return ""
        val 目标时间 = Instant.fromEpochSeconds(时间戳)
        val 目标时间日期 = 目标时间.toLocalDateTime(TimeZone.currentSystemDefault())
        return 格式化日期时间(目标时间日期)
    }

}

fun LocalDateTime.toEpochSeconds() : Long{
    return this.toInstant(TimeZone.currentSystemDefault()).epochSeconds
}